package com.hqyj.onlineExamination.modules.exam.service.impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.hqyj.onlineExamination.modules.account.entity.User;
import com.hqyj.onlineExamination.modules.common.entity.ResultEntity;
import com.hqyj.onlineExamination.modules.common.entity.SearchBean;
import com.hqyj.onlineExamination.modules.exam.dao.PaperDao;
import com.hqyj.onlineExamination.modules.exam.entity.Paper;
import com.hqyj.onlineExamination.modules.exam.entity.Question;
import com.hqyj.onlineExamination.modules.exam.entity.QuestionType;
import com.hqyj.onlineExamination.modules.exam.service.PaperService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.*;

import com.hqyj.onlineExamination.modules.account.entity.Role;
import com.hqyj.onlineExamination.modules.common.entity.ResultEntity;
import com.hqyj.onlineExamination.modules.common.entity.SearchBean;
import com.hqyj.onlineExamination.modules.exam.dao.PaperDao;
import com.hqyj.onlineExamination.modules.exam.dao.PaperQuestionDao;
import com.hqyj.onlineExamination.modules.exam.dao.QuestionDao;
import com.hqyj.onlineExamination.modules.exam.entity.Paper;
import com.hqyj.onlineExamination.modules.exam.entity.PaperQuestion;
import com.hqyj.onlineExamination.modules.exam.entity.Question;
import com.hqyj.onlineExamination.modules.exam.service.PaperService;
import com.hqyj.onlineExamination.modules.exam.service.QuestionService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import javax.transaction.Transactional;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Optional;

@Service
public class PaperServiceImpl implements PaperService {

    @Autowired
    private PaperDao paperDao;

    @Autowired
    private QuestionDao questionDao;

    @Autowired
    private QuestionService questionService;

    @Autowired
    private PaperQuestionDao paperQuestionDao;

    @Autowired
    private HttpServletRequest request;

    @Override
    public ResultEntity<Map<String, Object>> getAllPaperById(int id) {
        //创建一个map集合
        Map<String, Object> map = new HashMap<>();
        //查询数据库
        Paper paper = paperDao.getAllPaperById(id);
        if (paper == null) {
            return new ResultEntity<Map<String, Object>>(ResultEntity.ResultStatus.FAILED.status, "没有这张试卷！");
        }
        //将查到的内容装进map中
        map.put("paperId", paper.getId());
        map.put("time", paper.getTotalTime());
        //创建5个list集合来装不同的题型
        List<Question> listSingleChoice = new ArrayList<>();
        List<Question> listMultipleChoice = new ArrayList<>();
        List<Question> listJudge = new ArrayList<>();
        List<Question> listFillBlank = new ArrayList<>();
        List<Question> listShortAnswer = new ArrayList<>();
        List<Question> listProgramming = new ArrayList<>();
        //遍历循环questions
        for (Question question : paper.getQuestions()) {
            if (question.getType().equals(QuestionType.SINGLE_CHOICE.name)) {
                listSingleChoice.add(question);
            } else if (question.getType().equals(QuestionType.MULTIPLE_CHOICE.name)) {
                listMultipleChoice.add(question);
            } else if (question.getType().equals(QuestionType.JUDGE.name)) {
                listJudge.add(question);
            } else if (question.getType().equals(QuestionType.FILL_BLANK.name)) {
                listFillBlank.add(question);
            } else if (question.getType().equals(QuestionType.SHORT_ANSWER.name)) {
                listShortAnswer.add(question);
            } else if (question.getType().equals(QuestionType.PROGRAMMING.name)) {
                listProgramming.add(question);
            }
        }
        //将这些list全部装入map返回给前端
        map.put(QuestionType.SINGLE_CHOICE.name, listSingleChoice);
        map.put(QuestionType.MULTIPLE_CHOICE.name, listMultipleChoice);
        map.put(QuestionType.JUDGE.name, listJudge);
        map.put(QuestionType.FILL_BLANK.name, listFillBlank);
        map.put(QuestionType.SHORT_ANSWER.name, listShortAnswer);
        map.put(QuestionType.PROGRAMMING.name, listProgramming);
        return new ResultEntity<Map<String, Object>>(ResultEntity.ResultStatus.SUCCESS.status, "查询成功！", map);
    }

    @Override
    public Paper getPaperById(int id) {
        return paperDao.getPaperById(id);
    }

    @Override
    public Paper getPaperBySubject(String subject) {
        return paperDao.getPaperBySubject(subject);
    }

    /*
     * -随机生成题 规则：
     * -编程题 30 分，随机在对应集合中选择 2 道，对应集合不足 2 道则全部添加，每题 15 分
     * -简答题 10 分，随机在对应集合中选择 2 道，对应集合不足 2 道则全部添加，每题 5 分
     * -多选题 20 分，随机在对应集合中选择 2 道，对应集合不足 2 道则全部添加，每题 4 分
     * -填空题 10 分，随机在对应集合中选择 5 道，对应集合不足 5 道则全部添加，每题 2 分
     * -判断题 10 分，随机在对应集合中选择 5 道，对应集合不足 5 道则全部添加，每题 2 分
     * -单选题 20 分，随机在对应集合中选择 8 道，对应集合不足 8 道则全部添加，每题 4 分
     */
    @Override
    @Transactional
    public ResultEntity<Paper> insertPaper(Paper paper) {
        User user = (User) request.getSession().getAttribute("user");
        paper.setCreateDate(LocalDateTime.now());
        String paperType = paper.getPaperType();
        paper.setSubject(paperType + "_" + paper.getSubject() + "_" + user.getUserName());
        double totalScore = 0;
        List<String> typeList = new ArrayList<>();
        Map<String, List<Question>> questionMap = new HashMap();

        //如果数据库存在这个subject的试卷了
        Paper flag = paperDao.getPaperBySubject(paper.getSubject());
        if (flag != null) {
            return new ResultEntity<Paper>(ResultEntity.ResultStatus.FAILED.status, "命名重复，请重新输入试卷名称");
        } else {
            // 1.将生成的试卷加入paper表
            paperDao.insertPaper(paper);
        }
        // 获取生成试卷的试卷对象
        Paper paperInsert = paperDao.getPaperBySubject(paper.getSubject());
        // 2.根据选择的题目类型获取question表中对应question对象
        // 2.1 获取选择的题目类型
        List<Question> questionTypes = questionService.getTypes();
        List<Question> questions = paper.getQuestions();
        for (Question question : questions) {
            // 用户选择的题目类型id
            Integer userSelectId = question.getId();
            for (Question questionType : questionTypes) {
                if (questionType.getId() == userSelectId) {
                    typeList.add(questionType.getType());
                }
            }
        }
        System.err.println(typeList);
        // 3.获取对应的题目类型的题目，装在Map集合中
        // 遍历类型
        for (String type : typeList) {
            // 如果是单选题
            if (type.equals("singleChoice")) {
                // 获取单选题题库
                List<Question> singleChoiceQuestions = questionDao.getQuestionsByTypeAndFlag("singleChoice", paperType);
                questionMap.put("singleChoice", singleChoiceQuestions);
            } else if (type.equals("multipleChoice")) {
                List<Question> multipleChoiceQuestions = questionDao.getQuestionsByTypeAndFlag("multipleChoice", paperType);
                questionMap.put("multipleChoice", multipleChoiceQuestions);
            } else if (type.equals("fillBlank")) {
                List<Question> fillBlankQuestions = questionDao.getQuestionsByTypeAndFlag("fillBlank", paperType);
                questionMap.put("fillBlank", fillBlankQuestions);
            } else if (type.equals("shortAnswer")) {
                List<Question> shortAnswerQuestions = questionDao.getQuestionsByTypeAndFlag("shortAnswer", paperType);
                questionMap.put("shortAnswer", shortAnswerQuestions);
            } else if (type.equals("programming")) {
                List<Question> programmingQuestions = questionDao.getQuestionsByTypeAndFlag("programming", paperType);
                questionMap.put("programming", programmingQuestions);
            } else {
                List<Question> judgeQuestions = questionDao.getQuestionsByTypeAndFlag("judge", paperType);
                questionMap.put("judge", judgeQuestions);
            }
        }
        // 4.将paper_id和question_id添加到中间表
        Set<Map.Entry<String, List<Question>>> entries = questionMap.entrySet();
        Random random = new Random();
        for (Map.Entry<String, List<Question>> entry : entries) {
            // 如果是单选题
            if (entry.getKey().equals("singleChoice")) {
                List<Integer> newList = new ArrayList();
                // 单选题题库
                List<Question> singleChoice = entry.getValue();
                if (singleChoice.size() <= 8) {
                    for (Question question : singleChoice) {
                        paperQuestionDao.addPaperQuestionByPaperQuestion(
                                new PaperQuestion(paperInsert.getId(), question.getId()));
                        totalScore += 4;
                    }
                } else {
                    for (int i = 0; i < 8; i++) {
                        int index = random.nextInt(singleChoice.size());
                        if (newList.contains(index)) {
                            i--;
                            continue;
                        }
                        newList.add(index);
                        // 随机抽取一个问题
                        Question question = singleChoice.get(index);
                        paperQuestionDao.addPaperQuestionByPaperQuestion(
                                new PaperQuestion(paperInsert.getId(), question.getId()));
                        totalScore += 4;
                    }
                }
            } else if (entry.getKey().equals("multipleChoice")) {
                List<Integer> newList = new ArrayList();
                List<Question> multipleChoice = entry.getValue();
                if (multipleChoice.size() <= 2) {
                    for (Question question : multipleChoice) {
                        paperQuestionDao.addPaperQuestionByPaperQuestion(
                                new PaperQuestion(paperInsert.getId(), question.getId()));
                        totalScore += 4;
                    }
                } else {
                    // 大于8道题
                    for (int i = 0; i < 2; i++) {
                        int index = random.nextInt(multipleChoice.size());
                        if (newList.contains(index)) {
                            i--;
                            continue;
                        }
                        newList.add(index);
                        Question question = multipleChoice.get(index);
                        paperQuestionDao.addPaperQuestionByPaperQuestion(
                                new PaperQuestion(paperInsert.getId(), question.getId()));
                        totalScore += 4;
                    }
                }
            } else if (entry.getKey().equals("fillBlank")) {
                List<Integer> newList = new ArrayList();
                List<Question> fillBlank = entry.getValue();
                if (fillBlank.size() <= 5) {
                    for (Question question : fillBlank) {
                        paperQuestionDao.addPaperQuestionByPaperQuestion(
                                new PaperQuestion(paperInsert.getId(), question.getId()));
                        totalScore += 2;
                    }
                } else {
                    // 大于8道题
                    for (int i = 0; i < 5; i++) {
                        int index = random.nextInt(fillBlank.size());
                        if (newList.contains(index)) {
                            i--;
                            continue;
                        }
                        newList.add(index);
                        Question question = fillBlank.get(index);
                        paperQuestionDao.addPaperQuestionByPaperQuestion(
                                new PaperQuestion(paperInsert.getId(), question.getId()));
                        totalScore += 2;
                    }
                }
            } else if (entry.getKey().equals("shortAnswer")) {
                List<Integer> newList = new ArrayList();
                List<Question> shortAnswer = entry.getValue();
                if (shortAnswer.size() <= 2) {
                    for (Question question : shortAnswer) {
                        paperQuestionDao.addPaperQuestionByPaperQuestion(
                                new PaperQuestion(paperInsert.getId(), question.getId()));
                        totalScore += 5;
                    }
                } else {
                    for (int i = 0; i < 2; i++) {
                        int index = random.nextInt(shortAnswer.size());
                        if (newList.contains(index)) {
                            i--;
                            continue;
                        }
                        newList.add(index);
                        Question question = shortAnswer.get(index);
                        paperQuestionDao.addPaperQuestionByPaperQuestion(
                                new PaperQuestion(paperInsert.getId(), question.getId()));
                        totalScore += 5;
                    }
                }
            } else if (entry.getKey().equals("programming")) {
                List<Integer> newList = new ArrayList();
                List<Question> programming = entry.getValue();
                if (programming.size() <= 2) {
                    for (Question question : programming) {
                        paperQuestionDao.addPaperQuestionByPaperQuestion(
                                new PaperQuestion(paperInsert.getId(), question.getId()));
                        totalScore += 15;
                    }
                } else {
                    // 大于8道题
                    for (int i = 0; i < 2; i++) {
                        int index = random.nextInt(programming.size());
                        if (newList.contains(index)) {
                            i--;
                            continue;
                        }
                        newList.add(index);
                        Question question = programming.get(index);
                        paperQuestionDao.addPaperQuestionByPaperQuestion(
                                new PaperQuestion(paperInsert.getId(), question.getId()));
                        totalScore += 15;
                    }
                }
            } else {
                List<Integer> newList = new ArrayList();
                // 单选题题库
                List<Question> judge = entry.getValue();
                // 小于8道题
                if (judge.size() <= 5) {
                    for (Question question : judge) {
                        paperQuestionDao.addPaperQuestionByPaperQuestion(
                                new PaperQuestion(paperInsert.getId(), question.getId()));
                        totalScore += 2;
                    }
                } else {
                    // 大于8道题
                    for (int i = 0; i < 5; i++) {
                        // 产生一个随机数
                        int index = random.nextInt(judge.size());
                        // 如果之前抽过这个随机数了
                        if (newList.contains(index)) {
                            i--;
                            continue;
                        }
                        newList.add(index);
                        // 随机抽取一个问题
                        Question question = judge.get(index);
                        paperQuestionDao.addPaperQuestionByPaperQuestion(
                                new PaperQuestion(paperInsert.getId(), question.getId()));
                        totalScore += 2;
                    }
                }
            }
        }
        paper.setTotalScore(totalScore);
        paperDao.updatePaper(paper);
        return new ResultEntity<Paper>(ResultEntity.ResultStatus.SUCCESS.status, "Insert success", paper);
    }

    @Override
    @Transactional
    public ResultEntity<Paper> updatePaper(Paper paper) {
        paperDao.updatePaper(paper);
        return new ResultEntity<Paper>(ResultEntity.ResultStatus.SUCCESS.status, "Update success", paper);
    }

    @Override
    @Transactional
    public ResultEntity<Paper> deletePaperById(int id) {
        paperDao.deletePaperById(id);
        return new ResultEntity<Paper>(ResultEntity.ResultStatus.SUCCESS.status, "Delete success");
    }

    @Override
    @Transactional
    public PageInfo<Paper> getPapersBySearchBean(SearchBean searchBean) {
        //初始化当前页、页长、排序
        searchBean.initSearchBean();
        PageHelper.startPage(searchBean.getCurrentPage(), searchBean.getPageSize());
        return new PageInfo<Paper>(Optional
                .ofNullable(paperDao.getPapersBySearchBean(searchBean))
                .orElse(Collections.emptyList()));
    }
}
